import { Upload, Button } from 'antd';
import { LoadingOutlined, PlusOutlined, UploadOutlined } from '@ant-design/icons';
import config from '@/config/config.js'
import { host } from '@/utils/request';
import { useState, useEffect } from 'react';
import { FormattedMessage } from 'umi';
import { v4 as uuidv4 } from 'uuid';
import ImgCrop from 'antd-img-crop';
import styles from './styles.less';
import { getOssSignature, localUploadFile, ossUploadFile } from '@/services/common'


const getBase64 = (img, callback) => {
    const reader = new FileReader();
    reader.addEventListener('load', () => callback(reader.result));
    reader.readAsDataURL(img);
}

const beforeUploadGloabl = (file, maxSize) => {
    const sizeCheck = file.size / 1024 / 1024 < (maxSize || 2);
    if (!sizeCheck) {
        message.error(`文件大于${maxSize || 2},不能上传。`);
    }
    return sizeCheck;
}

const onPreview = async file => {
    let src = file.url;
    if (!src) {
        src = await new Promise(resolve => {
            const reader = new FileReader();
            reader.readAsDataURL(file.originFileObj);
            reader.onload = () => resolve(reader.result);
        });
    }
    const image = new Image();
    image.src = src;
    const imgWindow = window.open(src);
    imgWindow.document.write(image.outerHTML);
};

const getFileName = (file) => {
    if (file.name.indexOf(".")) {
        return uuidv4() + '.' + file.name.split(".")[1];
    } else {
        return uuidv4();
    }
}


const getTotalFileName = (file, dir, fileName) => {
    let realFileName = fileName || getFileName(file)
    if (dir) {
        return dir + "/" + realFileName;
    }
    return realFileName;
}

const uploadFileManual = async ({
    file,
    dir,
    fileName,
    acl,
    onSuccess,
    onError
}) => {
    const formData = new FormData();
    formData.append("dir", dir);
    const uploadAction = config.uploadAction;
    if ("local" === "local") {
        if (fileName) {
            formData.append("fileName", fileName)
        }
        formData.append("file", file);
        const result = await localUploadFile(formData)
        console.log(result)
        if (result?.success) {
            if (onSuccess) {
                onSuccess(`${host}/common/file/${result?.data}`)
            }
        } else {
            if (onError) {
                onError(result?.data)
            }
        }
    } else {
        let ossSignatureResult = await getOssSignature(dir || "")
        if (!ossSignatureResult.success) {
            message.error("获取Oss签名失败")
            return false;
        }
        let ossSignature = ossSignatureResult.data
        let key = getTotalFileName(file, dir, fileName);
        formData.append("key", key)
        formData.append("OSSAccessKeyId", ossSignature.accessKeyId)
        formData.append("policy", ossSignature.policy)
        formData.append("Signature", ossSignature.signature)
        formData.append("success_action_status", "200")
        formData.append("x-oss-object-acl", acl || "default")
        formData.append("file", file);
        const res = await ossUploadFile(ossSignature.host, formData)
        if (onSuccess) {
            onSuccess(`${ossSignature.host}/${key}`)
        }
    }
}

class AliyunUpload extends React.Component {
    state = {
        ossData: {},
    };
    getExtraData = file => {
        const { ossData } = this.state;
        const { data } = this.props;
        let key = getTotalFileName(file, data.dir, data.fileName);
        this.setState({
            key: key,
        });
        return {
            key: key,
            OSSAccessKeyId: ossData.accessKeyId,
            policy: ossData.policy,
            Signature: ossData.signature,
            success_action_status: "200",
            "x-oss-object-acl": data.acl || "default"
        };
    };

    ossBeforeUpload = async (file) => {
        const { beforeUpload, maxSize } = this.props;
        let ret = true;
        if (beforeUpload) {
            ret = beforeUpload(file)
        }
        const ifPermit = beforeUploadGloabl(file, maxSize);
        if (!ret || !ifPermit) {
            return ret;
        }
        await this.initOssSignature()
        return ret;
    }

    initOssSignature = async () => {
        const {
            data,
        } = this.props;
        let result = await getOssSignature(data?.dir)
        this.setState({
            ossData: result?.data,
        });
    }

    handleChange = (info) => {
        const { ossData, key } = this.state;
        const { onLoading, onLoadDone, haseBase64 } = this.props;
        if (info.file.status === 'uploading') {
            if (onLoading) {
                onLoading(info)
            }
            return;
        }
        if (info.file.status === 'done') {
            // Get this url from response in real world.
            if (haseBase64) {
                getBase64(info.file.originFileObj, imageUrl => {
                    onLoadDone({
                        fileUrl: `${ossData.host}/${key}`,
                        base64Url: imageUrl
                    })
                });
            } else {
                onLoadDone({
                    fileUrl: `${ossData.host}/${key}`,
                })
            }
            // setImageUrl(`${host}/common/file/${info.file.response.data}`);
        }
    }
    render() {
        const {
            content,
            listType,
            accept,
            className
        } = this.props;
        const { ossData } = this.state;
        return (
            <Upload
                name="file"
                accept={accept}
                listType={listType}
                showUploadList={false}
                action={ossData?.host}
                beforeUpload={this.ossBeforeUpload}
                onChange={this.handleChange}
                data={this.getExtraData}
                onPreview={onPreview}
                className={className}
            >
                {content}
            </Upload>
        )
    }

}

const LocalUpload = (props) => {
    const {
        beforeUpload,
        data,
        content,
        onLoading,
        onLoadDone,
        maxSize,
        listType,
        haseBase64,
        accept = "image/png, image/jpeg",
        className
    } = props;

    const handleChange = (info) => {

        if (info.file.status === 'uploading') {
            if (onLoading) {
                onLoading(info)
            }
            return;
        }
        if (info.file.status === 'done') {
            // Get this url from response in real world.
            if (haseBase64) {
                getBase64(info.file.originFileObj, imageUrl => {
                    onLoadDone({
                        fileUrl: `${host}/common/file/${info.file.response.data}`,
                        base64Url: imageUrl
                    })
                });
            } else {
                onLoadDone({
                    fileUrl: `${host}/common/file/${info.file.response.data}`,
                })
            }

            // setImageUrl(`${host}/common/file/${info.file.response.data}`);
        }
    }
    const localBeforeUpload = (file) => {
        if (beforeUpload) {
            ret = beforeUpload(file)
        }
        const ifPermit = beforeUploadGloabl(file, maxSize);
        return ret && ifPermit;
    }

    return (

        <Upload
            name="file"
            accept={accept}
            listType={listType}
            showUploadList={false}
            action={host + "/common/file/upload"}
            beforeUpload={localBeforeUpload}
            onChange={handleChange}
            data={data}
            onPreview={onPreview}
            className={className}
        >
            {content}
        </Upload>
    )
}


const UsedUpload = (props) => {
    const uploadAction = config.uploadAction;
    if (uploadAction === "local") {
        return <LocalUpload {...props}></LocalUpload>
    }
    return <AliyunUpload {...props}></AliyunUpload>
}

const CircleAvatarUpload = (props) => {
    const {
        onChange,
        value,
        isCrop,
    } = props;
    const [loading, setLoading] = useState(false)
    const [imageUrl, setImageUrl] = useState();
    const [data, setData] = useState({
        dir: "avatar",
        acl: "public-read"
    })

    useEffect(() => {
        setImageUrl(value)
    }, [value])

    const beforeUpload = (file) => {
        const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
        if (!isJpgOrPng) {
            message.error('You can only upload JPG/PNG file!');
        };
        data.fileName = getFileName(file);
        setData(data)
        return isJpgOrPng;
    }
    const content = (<div className={styles.button_view}>
        <Button>
            <UploadOutlined />
            <FormattedMessage
                id="common.change-avatar"
                defaultMessage="Change avatar"
            />
        </Button>
    </div>)

    const uploadRender = (
        <UsedUpload
            beforeUpload={beforeUpload}
            data={data}
            onLoading={() => {
                setLoading(true)
            }}
            className={styles.defaultAvatar}
            haseBase64={true}
            onLoadDone={(data) => {
                setLoading(false);
                if (onChange) {
                    onChange(data.fileUrl)
                }
                setImageUrl(data.base64Url);
            }}
            content={content}
        ></UsedUpload>
    );

    return (
        <div>
            <div className={styles.avatar} loading={loading}>
                <img src={imageUrl} alt="avatar" />
            </div>
            {isCrop ?
                (<ImgCrop rotate>
                    {uploadRender}
                </ImgCrop>)
                : uploadRender
            }
        </div>
    )
}

const AvatarUpload = (props) => {
    const {
        onChange,
        value,
        isCrop,
    } = props;

    const [loading, setLoading] = useState(false)
    const [imageUrl, setImageUrl] = useState("")
    const [data, setData] = useState({
        dir: "avatar",
        acl: "public-read"
    })
    useEffect(() => {
        setImageUrl(value)
    }, [value])

    const beforeUpload = (file) => {
        const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
        if (!isJpgOrPng) {
            message.error('You can only upload JPG/PNG file!');
        };
        data.fileName = getFileName(file);
        setData(data)
        return isJpgOrPng;
    }

    const uploadButton = (
        <div>
            {loading ? <LoadingOutlined /> : <PlusOutlined />}
            <div style={{ marginTop: 8 }}>上传</div>
        </div>
    );

    const content = (<div className={styles.defaultAvatar}>
        {imageUrl ? <img src={imageUrl} alt="avatar" /> : uploadButton}
    </div>)

    const uploadRender = (
        <UsedUpload
            beforeUpload={beforeUpload}
            data={data}
            listType="picture-card"
            onLoading={() => {
                setLoading(true)
            }}
            haseBase64={true}
            onLoadDone={(data) => {
                console.log(data)
                setLoading(false);
                setImageUrl(data.base64Url);
                if (onChange) {
                    onChange(data.fileUrl)
                }
            }}
            content={content}
        ></UsedUpload>
    );

    return (
        <>
            {isCrop ?
                (<ImgCrop rotate>
                    {uploadRender}
                </ImgCrop>)
                : uploadRender
            }
        </>
    )
}

export { AvatarUpload, CircleAvatarUpload, UsedUpload, uploadFileManual };

export default (props) => {
    const { } = props;
    return (
        <Upload
            {...props}
        ></Upload>
    )
}

